﻿using InvestmentIntelligence.TradingData.Adapters.Mus.Enums;
using InvestmentIntelligence.TradingData.Adapters.Mus.MarketIndicators.TimeLineBuilders;
using InvestmentIntelligence.TradingData.DataProcessing.DataResolvers;
using System.Collections.Generic;
using System.Linq;

namespace InvestmentIntelligence.TradingData.Adapters.Mus.MarketIndicators.TrendIndicators
{
    class ExponentialMovingAverageIndicator : TrendIndicator
    {
        public override TrendIndicatorTypes Type
        {
            get { return TrendIndicatorTypes.Ema; }
        }

        public override Dictionary<TrendTypes, TrendActions> Indicate(int securityId, List<TimeSerieInfo> timeSeries)
        {
            var result = PrepareOutput();
            
            var isTimeSeriesValid = timeSeries.All(s => s.ClosePrice > 0);
            if (!isTimeSeriesValid)
            {
                result[TrendTypes.LongBigTerm] = TrendActions.Close;
                result[TrendTypes.LongMediumTerm] = TrendActions.Close;
                result[TrendTypes.LongSmallTerm] = TrendActions.Close;
                result[TrendTypes.ShortBigTerm] = TrendActions.Close;
                result[TrendTypes.ShortMediumTerm] = TrendActions.Close;
                result[TrendTypes.ShortSmallTerm] = TrendActions.Close;

                return result;
            }

            var ema5 = new ExponentialMovingAverageTimelineBuilder(5);
            var ema10 = new ExponentialMovingAverageTimelineBuilder(10);
            var ema25 = new ExponentialMovingAverageTimelineBuilder(25);
            var ema50 = new ExponentialMovingAverageTimelineBuilder(50);
            var ema100 = new ExponentialMovingAverageTimelineBuilder(100);
            var ema200 = new ExponentialMovingAverageTimelineBuilder(200);

            timeSeries = timeSeries.OrderBy(t => t.Date).ToList(); // this need to be already sorted

            var ema5Series = ema5.Build(timeSeries);
            var ema10Series = ema10.Build(timeSeries);
            var ema25Series = ema25.Build(timeSeries);
            var ema50Series = ema50.Build(timeSeries);
            var ema100Series = ema100.Build(timeSeries);
            var ema200Series = ema200.Build(timeSeries);

            // take 2 last elements only
            ema5Series = ema5Series.SkipWhile((t, i) => i < ema5Series.Count - 2).ToList();
            ema10Series = ema10Series.SkipWhile((t, i) => i < ema10Series.Count - 2).ToList();
            ema25Series = ema25Series.SkipWhile((t, i) => i < ema25Series.Count - 2).ToList();
            ema50Series = ema50Series.SkipWhile((t, i) => i < ema50Series.Count - 2).ToList();
            ema100Series = ema100Series.SkipWhile((t, i) => i < ema100Series.Count - 2).ToList();
            ema200Series = ema200Series.SkipWhile((t, i) => i < ema200Series.Count - 2).ToList();

            var ema5PrevLast = ema5Series.First();
            var ema10PrevLast = ema10Series.First();
            var ema25PrevLast = ema25Series.First();
            var ema50PrevLast = ema50Series.First();
            var ema100PrevLast = ema100Series.First();
            var ema200PrevLast = ema200Series.First();

            var ema5Last = ema5Series.Last();
            var ema10Last = ema10Series.Last();
            var ema25Last = ema25Series.Last();
            var ema50Last = ema50Series.Last();
            var ema100Last = ema100Series.Last();
            var ema200Last = ema200Series.Last();

            result[TrendTypes.LongBigTerm] = GetTrendAction(true, ema50PrevLast.Value, ema50Last.Value, ema200PrevLast.Value, ema200Last.Value);
            result[TrendTypes.LongMediumTerm] = GetTrendAction(true, ema25PrevLast.Value, ema25Last.Value, ema100PrevLast.Value, ema100Last.Value);
            result[TrendTypes.LongSmallTerm] = GetTrendAction(true, ema10PrevLast.Value, ema10Last.Value, ema50PrevLast.Value, ema50Last.Value);
            result[TrendTypes.ShortBigTerm] = GetTrendAction(false, ema25PrevLast.Value, ema25Last.Value, ema100PrevLast.Value, ema100Last.Value);
            result[TrendTypes.ShortMediumTerm] = GetTrendAction(false, ema10PrevLast.Value, ema10Last.Value, ema50PrevLast.Value, ema50Last.Value);
            result[TrendTypes.ShortSmallTerm] = GetTrendAction(false, ema5PrevLast.Value, ema5Last.Value, ema25PrevLast.Value, ema25Last.Value);

            return result;
        }

        private static TrendActions GetTrendAction(bool longTrendDetection, decimal shorterPrevEma, decimal shorterEma, decimal longerPrevEma, decimal longerEma)
        {
            var result = TrendActions.None;
            if (longTrendDetection)
            {
                if (shorterPrevEma < longerPrevEma && shorterEma > longerEma)
                {
                    result = TrendActions.Open;
                }
                else if (shorterEma < longerEma)
                {
                    result = TrendActions.Close;
                }
                //todo: think about Increase/Decrease
                //else if ()
                //{
                    
                //}
            }
            else
            {
                if (shorterEma > longerEma)
                {
                    result = TrendActions.Close;
                }
                else if (shorterPrevEma > longerPrevEma && shorterEma < longerEma)
                {
                    result = TrendActions.Open;
                }
                //todo: think about Increase/Decrease
                //else if ()
                //{
                    
                //}
            }

            return result;
        }
    }
}